package com.xjaq.dify.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.xjaq.dify.common.Result;
import com.xjaq.dify.entity.*;
import com.xjaq.dify.service.IPsyAiChatService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Map;
import java.util.Objects;
@ApiSort(value = 0)
@Api(tags = "AI")
@RequiredArgsConstructor
@RestController
@Slf4j
@RequestMapping("/ai")
public class PsyAiChatController {
 
    //流式模式
    private final static String STREAMING_MODE = "streaming";
    //阻塞模式
    private final static String BLOCKING_MODE = "blocking";
 
    @Resource
    private IPsyAiChatService difyChatService;

    @ApiOperation(value = "1.聊天", notes = "创建会话消息")
    @ApiOperationSupport(order = 1)
    @PostMapping(path = "/chat-messages")
    @ResponseBody
    public ResponseBodyEmitter chatMessages(
            @ApiParam(value = "聊天请求参数", required = true)
            @RequestBody @Valid DifyRequest difyRequest,
            HttpServletResponse response) {
        
        // 设置默认响应模式为流式
        if (ObjectUtils.isEmpty(difyRequest.getResponseMode())) {
            difyRequest.setResponseMode(STREAMING_MODE);
        }
        
        // 根据response_mode设置响应类型
        if ("blocking".equals(difyRequest.getResponseMode())) {
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        } else {
            response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE);
            response.setCharacterEncoding("UTF-8");
        }
        
        // 添加CORS头部
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
        
        return difyChatService.sseChatPrompt(difyRequest);
    }
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "2.上传文件", notes = "上传文件并在发送消息时使用，可实现图文多模态理解")
    @PostMapping(path = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseBody
    public Result uploadFile(
            @ApiParam(value = "要上传的文件", required = true)
            @RequestPart("file") MultipartFile file,
            @ApiParam(value = "用户标识，用于定义终端用户的身份，必须和发送消息接口传入 user 保持一致", required = true)
            @RequestParam("user") String user) {
        try {
            return difyChatService.uploadFile(file, user);
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return Result.error("文件上传失败: " + e.getMessage());
        }
    }
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "3.停止响应", notes = "仅支持流式模式")
    @PostMapping("/chat-messages/{task_id}/stop")
    @ResponseBody
    public Result stopChatResponse(
            @ApiParam(value = "任务ID，可在流式返回Chunk中获取", required = true)
            @PathVariable("task_id") String taskId,
            @ApiParam(value = "用户标识，用于定义终端用户的身份，必须和发送消息接口传入 user 保持一致", required = true)
            @RequestBody StopChatRequest requestBody) {

        String user = requestBody.getUser();
        if (user == null || user.isEmpty()) {
            return Result.error("用户标识不能为空");
        }
        
        Result result = difyChatService.stopChatTask(taskId, user);
        return result;
    }
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "4.消息反馈", notes = "消息终端用户反馈、点赞")
    @PostMapping("/messages/{message_id}/feedbacks")
    @ResponseBody
    public Result messageFeedback(
            @ApiParam(value = "消息 ID", required = true)
            @PathVariable("message_id") String messageId,
            @ApiParam(value = "消息反馈请求参数", required = true)
            @RequestBody @Valid FeedbackRequest feedbackRequest) {
        
        return difyChatService.messageFeedback(messageId, feedbackRequest);
    }

    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "5.获取应用反馈", notes = "获取应用的终端用户反馈、点赞")
    @GetMapping("/app/feedbacks")
    @ResponseBody
    public Result getAppFeedbacks(
            @ApiParam(value = "页码，默认值：1")
            @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
            @ApiParam(value = "每页数量，默认值：20")
            @RequestParam(value = "limit", required = false, defaultValue = "20") Integer limit) {

        return difyChatService.getAppFeedbacks(page, limit);
    }
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "6.获取建议问题", notes = "获取下一轮建议问题列表")
    @GetMapping("/messages/{messageId}/suggested")
    @ResponseBody
    public Result getSuggestedQuestions(
            @ApiParam(value = "消息 ID", required = true)
            @PathVariable("messageId") String messageId,
            @ApiParam(value = "用户标识，由开发者定义规则，需保证用户标识在应用内唯一", required = true)
            @RequestParam("user") String user) {

        return difyChatService.getSuggestedQuestions(messageId, user);
    }
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "7.获取消息历史", notes = "滚动加载形式返回历史聊天记录")
    @GetMapping("/messages")
    @ResponseBody
    public Result getMessageHistory(
            @ApiParam(value = "会话ID")
            @RequestParam(value = "conversation_id", required = false) String conversationId,
            @ApiParam(value = "用户标识，由开发者定义规则，需保证用户标识在应用内唯一", required = true)
            @RequestParam("user") String user,
            @ApiParam(value = "当前页第一条聊天记录的ID，默认null")
            @RequestParam(value = "first_id", required = false) String firstId,
            @ApiParam(value = "一次请求返回多少条聊天记录，默认20条")
            @RequestParam(value = "limit", required = false, defaultValue = "20") Integer limit) {

        MessageHistoryQuery query = new MessageHistoryQuery();
        query.setConversationId(conversationId);
        query.setUser(user);
        query.setFirstId(firstId);
        query.setLimit(limit);

        return difyChatService.getMessageHistory(query);
    }
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "8.获取会话列表", notes = "获取当前用户的会话列表，默认返回最近的20条")
    @GetMapping("/conversations")
    @ResponseBody
    public Result getConversations(
            @ApiParam(value = "用户标识，由开发者定义规则，需保证用户标识在应用内唯一", required = true)
            @RequestParam("user") String user,
            @ApiParam(value = "当前页最后面一条记录的ID，默认null")
            @RequestParam(value = "last_id", required = false) String lastId,
            @ApiParam(value = "一次请求返回多少条记录，默认20条，最大100条，最小1条")
            @RequestParam(value = "limit", required = false, defaultValue = "20") Integer limit,
            @ApiParam(value = "排序字段，默认-updated_at(按更新时间倒序排列)")
            @RequestParam(value = "sort_by", required = false, defaultValue = "-updated_at") String sortBy) {

        ConversationQuery query = new ConversationQuery();
        query.setUser(user);
        query.setLastId(lastId);
        query.setLimit(limit);
        query.setSortBy(sortBy);

        return difyChatService.getConversations(query);
    }
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "9.删除会话", notes = "删除会话")
    @DeleteMapping("/conversations/{conversationId}")
    @ResponseBody
    public Result deleteConversation(
            @ApiParam(value = "会话ID", required = true)
            @PathVariable("conversationId") String conversationId,
            @ApiParam(value = "用户标识，由开发者定义规则，需保证用户标识在应用内唯一", required = true)
            @RequestBody @Valid DeleteConversationRequest deleteRequest) {

        return difyChatService.deleteConversation(conversationId, deleteRequest.getUser());
    }
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "10.会话重命名", notes = "对会话进行重命名，会话名称用于显示在支持多会话的客户端上")
    @PostMapping("/conversations/{conversationId}/name")
    @ResponseBody
    public Result renameConversation(
            @ApiParam(value = "会话ID", required = true)
            @PathVariable("conversationId") String conversationId,
            @ApiParam(value = "会话重命名请求参数", required = true)
            @RequestBody @Valid ConversationRenameRequest renameRequest) {

        return difyChatService.renameConversation(conversationId, renameRequest);
    }
    @ApiOperationSupport(order = 11)
    @ApiOperation(value = "11.获取对话变量", notes = "从特定对话中检索变量。此端点对于提取对话过程中捕获的结构化数据非常有用。")
    @GetMapping("/conversations/{conversationId}/variables")
    @ResponseBody
    public Result getConversationVariables(
            @ApiParam(value = "对话ID", required = true)
            @PathVariable("conversationId") String conversationId,
            @ApiParam(value = "用户标识符，由开发人员定义的规则，在应用程序内必须唯一", required = true)
            @RequestParam("user") String user,
            @ApiParam(value = "当前页最后面一条记录的ID，默认null")
            @RequestParam(value = "last_id", required = false) String lastId,
            @ApiParam(value = "一次请求返回多少条记录，默认20条，最大100条，最小1条")
            @RequestParam(value = "limit", required = false, defaultValue = "20") Integer limit,
            @ApiParam(value = "变量名称过滤器（可选）")
            @RequestParam(value = "variable_name", required = false) String variableName) {

        ConversationVariablesQuery query = new ConversationVariablesQuery();
        query.setUser(user);
        query.setLastId(lastId);
        query.setLimit(limit);
        query.setVariableName(variableName);

        return difyChatService.getConversationVariables(conversationId, query);
    }
    @ApiOperationSupport(order = 12)
    @ApiOperation(value = "12.语音转文字", notes = "将语音文件转换为文字")
    @PostMapping("/audio-to-text")
    @ResponseBody
    public Result audioToText(
            @ApiParam(value = "语音文件。支持格式：['mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm'] 文件大小限制：15MB", required = true)
            @RequestPart("file") MultipartFile file,
            @ApiParam(value = "用户标识，由开发者定义规则，需保证用户标识在应用内唯一", required = true)
            @RequestParam("user") String user) {

        AudioToTextRequest request = new AudioToTextRequest();
        request.setFile(file);
        request.setUser(user);

        return difyChatService.audioToText(request);
    }
    @ApiOperationSupport(order = 13)
    @ApiOperation(value = "13.文字转语音", notes = "将文字转换为语音")
    @PostMapping("/text-to-audio")
    @ResponseBody
    public void textToAudio(
            @ApiParam(value = "文字转语音请求参数", required = true)
            @RequestBody @Valid TextToAudioRequest textToAudioRequest,
            HttpServletResponse response) {

        try {
            Result result = difyChatService.textToAudio(textToAudioRequest);

            if (Objects.equals(result.getCode(), Result.SUCCESS_CODE) && result.getData() != null) {
                // 获取音频数据
                Map<String, Object> data = (Map<String, Object>) result.getData();
                byte[] audioData = (byte[]) data.get("audioData");
                String contentType = (String) data.get("contentType");

                // 设置响应头
                response.setContentType(contentType != null ? contentType : "audio/wav");
                response.setContentLength(audioData.length);
                response.setHeader("Content-Disposition", "inline; filename=\"text-to-audio.wav\"");

                // 写入音频数据到响应流
                response.getOutputStream().write(audioData);
                response.getOutputStream().flush();
            } else {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write(result.getMsg());
            }
        } catch (Exception e) {
            log.error("文字转语音处理异常", e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("文字转语音处理异常: " + e.getMessage());
            } catch (Exception ex) {
                log.error("写入错误响应失败", ex);
            }
        }
    }
    @ApiOperationSupport(order = 14)
    @ApiOperation(value = "14.获取应用基本信息", notes = "用于获取应用的基本信息")
    @GetMapping("/info")
    @ResponseBody
    public Result getAppInfo() {
        return difyChatService.getAppInfo();
    }

    @ApiOperationSupport(order = 15)
    @ApiOperation(value = "15.获取应用Meta信息", notes = "用于获取工具图标等Meta信息")
    @GetMapping("/meta")
    @ResponseBody
    public Result getAppMeta() {
        return difyChatService.getAppMeta();
    }
    @ApiOperationSupport(order = 16)
    @ApiOperation(value = "16.获取WebApp设置", notes = "用于获取应用的WebApp设置")
    @GetMapping("/site")
    @ResponseBody
    public Result getWebAppSettings() {
        return difyChatService.getWebAppSettings();
    }

    @ApiOperationSupport(order = 17)
    @ApiOperation(value = "17.获取标注列表", notes = "获取应用的标注列表")
    @GetMapping("/apps/annotations")
    @ResponseBody
    public Result getAnnotations(
            @ApiParam(value = "页码", defaultValue = "1")
            @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
            @ApiParam(value = "每页数量", defaultValue = "20")
            @RequestParam(value = "limit", required = false, defaultValue = "20") Integer limit) {
        return difyChatService.getAnnotations(page, limit);
    }

    @ApiOperationSupport(order = 18)
    @ApiOperation(value = "18.创建标注", notes = "创建新的标注")
    @PostMapping("/apps/annotations")
    @ResponseBody
    public Result createAnnotation(
            @ApiParam(value = "创建标注请求参数", required = true)
            @RequestBody @Valid CreateAnnotationRequest createAnnotationRequest) {
        return difyChatService.createAnnotation(createAnnotationRequest);
    }
    
    @ApiOperationSupport(order = 19)
    @ApiOperation(value = "19.更新标注", notes = "根据ID更新标注")
    @PutMapping("/apps/annotations/{annotation_id}")
    @ResponseBody
    public Result updateAnnotation(
            @ApiParam(value = "标注ID", required = true)
            @PathVariable("annotation_id") String annotationId,
            @ApiParam(value = "更新标注请求参数", required = true)
            @RequestBody @Valid UpdateAnnotationRequest updateAnnotationRequest) {
        return difyChatService.updateAnnotation(annotationId, updateAnnotationRequest);
    }
    
    @ApiOperationSupport(order = 20)
    @ApiOperation(value = "20.删除标注", notes = "根据ID删除标注")
    @DeleteMapping("/apps/annotations/{annotation_id}")
    @ResponseBody
    public Result deleteAnnotation(
            @ApiParam(value = "标注ID", required = true)
            @PathVariable("annotation_id") String annotationId) {
        return difyChatService.deleteAnnotation(annotationId);
    }

    @ApiOperationSupport(order = 21)
    @ApiOperation(value = "21.标注回复设置", notes = "标注回复初始设置，动作只能是 'enable' 或 'disable'")
    @PostMapping("/apps/annotation-reply/{action}")
    @ResponseBody
    public Result annotationReply(
            @ApiParam(value = "动作，只能是 'enable' 或 'disable'", required = true, allowableValues = "enable,disable")
            @PathVariable("action") String action,
            @ApiParam(value = "标注回复设置请求参数", required = true)
            @RequestBody @Valid AnnotationReplyRequest annotationReplyRequest) {
        // 验证 action 参数只能是 'enable' 或 'disable'
        if (!"enable".equals(action) && !"disable".equals(action)) {
            return Result.error("action 参数只能是 'enable' 或 'disable'");
        }
        return difyChatService.annotationReply(action, annotationReplyRequest);
    }
    
    @ApiOperationSupport(order = 22)
    @ApiOperation(value = "22.查询标注回复任务状态", notes = "查询标注回复初始设置任务状态")
    @GetMapping("/apps/annotation-reply/{action}/status/{job_id}")
    @ResponseBody
    public Result getAnnotationReplyStatus(
            @ApiParam(value = "动作，只能是 'enable' 或 'disable'", required = true, allowableValues = "enable,disable")
            @PathVariable("action") String action,
            @ApiParam(value = "任务 ID", required = true)
            @PathVariable("job_id") String jobId) {
        // 验证 action 参数只能是 'enable' 或 'disable'
        if (!"enable".equals(action) && !"disable".equals(action)) {
            return Result.error("action 参数只能是 'enable' 或 'disable'");
        }
        return difyChatService.getAnnotationReplyStatus(action, jobId);
    }

}